import re
from pathlib import Path
import mmap
import yaml
from lly.logconfig import logger

re_flags_dict = {
    "A": re.ASCII,
    "I": re.IGNORECASE,
    "L": re.LOCALE,
    "M": re.MULTILINE,
    "S": re.DOTALL,
    "X": re.VERBOSE,
}
newline_re = re.compile(r'\n')


def get_analysis(anaylysis_path):
    '''得到分析的正则配置信息

    分析文件为yaml格式，组成为

    '''
    content = Path(anaylysis_path).expanduser().read_text()
    analysis = yaml.safe_load(content)
    logger.debug(analysis)
    analysis_list = []
    for item in analysis['analysis']:
        flags = -1
        if 'flags' in item and not item['flags'] is None and len(item.get('flags', '')) > 0:
            flags = 0
            for flag in item['flags']:
                flags = flags | re_flags_dict.get(flag, 0)
        if flags != -1:
            analysis_list.append(
                (re.compile(item['re'], flags), item.get('type', '')))
        else:
            analysis_list.append(
                (re.compile(item['re']), item.get('type', '')))

    return (analysis_list, analysis['title'])


def analysis_files(analysis_info, log_paths):
    result = []
    if not isinstance(log_paths, list):
        logger.debug(f"analysis_file 1 path :{log_paths}")
        log_paths = [log_paths]
    for path in log_paths:
        logger.debug(f"analysis_file 2 path :{path}")
        items = analysis_file(analysis_info, path)
        if items:
            result.extend(items)
    logger.debug(f"analysis_files: {result}")
    return result


def analysis_file(analysis_info, log_path, errors="ignore"):
    '''
    使用analysis_list 分析log_path文件，
    并返回分析结果
    '''
    result = []
    content = None
    for encoding in['UTF-8', 'GBK']:
        try:
            with Path(log_path).expanduser().open('r+', encoding=encoding, errors=errors) as f:
                #  content = mmap.mmap(f.fileno(), 0).read()
                content = f.read()
                #  print(content)
                newline_position_list = []
                for match in re.finditer(newline_re, content):
                    newline_position_list.append(match.start())

                for analysis, type in analysis_info[0]:
                    for match in re.finditer(analysis, content):
                        #  print(match.group())
                        #  print(match.groupdict())
                        lnum, col = get_line_number_and_col(
                            newline_position_list, match.start())
                        type = match.groupdict['type'] if 'type' in match.groupdict(
                        ) else type
                        item = {'lnum': lnum, 'col': col, 'filename': str(log_path),
                                'text': match.group(), 'type': type}
                        result.append(item)
            break
        except Exception as e:
            print(encoding)
            continue


    logger.debug(f"analysis_file: {result}")
    return result


def get_line_number_and_col(newline_position_list, position):
    '''得到指定位置字符的行号与列号
    '''
    for line_number, newline_position in enumerate(newline_position_list):
        if position < newline_position:
            return (line_number+1, position-newline_position_list[line_number-1])


if __name__ == "__main__":
    file_path = "/Users/liluyue/.nvim/plugin/rplugin/python3/config/analysis/test.yaml"
    analysis_list = get_analysis(file_path)
    print(analysis_files(analysis_list,
                         list(Path('/Users/liluyue/.nvim/temp/android/').glob(r'*'))))
